#include	"a_global_vars.h"

//--------------------------------------------------------------------------------------------------------------------------
config_info * get_config_info() {
	return config_info_sample;
}
//-------------------------------------------------------------
void parse_config_file(const char * config_path, int process_id) {

	char flag;
	char *match;
	config_info_sample = (config_info*) malloc(sizeof(config_info));

	assert(config_info_sample != NULL);
	config_info_sample->self_id = process_id;

	match = "acceptor";
	flag = 'a';
	get_ip_port(config_path, get_config_info(), match, flag);

	match = "num_learners";
	config_info_sample->num_learners_to_connect_to_one_acceptor = read_a_number(config_path, get_config_info(), match);

	match = "learner";
	flag = 'l';
	get_ip_port(config_path, get_config_info(), match, flag);

	match = "learner_to_acceptor";
	flag = 't';
	get_ip_port(config_path, get_config_info(), match, flag);

	match = "multicast";
	get_multicast_address(config_path, config_info_sample, match);

	match = "proposer_to_multicaster";
	get_multicast_address_for_proposer(config_path, config_info_sample, match);

	create_sockets(config_info_sample);
	form_ring(config_info_sample);
}
//-------------------------------------------------------------
int read_a_number(const char* config_file, config_info * config, const char * match) {
	FILE * fp;
	char line[STRING_SIZE];
	char word[STRING_SIZE];
	int last_index = -1;

	fp = fopen(config_file, "r");
	assert(fp != NULL);

	while (!feof(fp)) {
		if (fgets(line, STRING_SIZE, fp) != 0) {
			last_index = get_substr(0, strlen(line) - 1, line, word);

			if (strcmp(word, match) == 0) {
				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				return atoi(word);
			}
		}
	}
	return -1;
}
//-------------------------------------------------------------
void get_ip_port(const char* config_file, config_info * config, const char * match, char flag) {

	FILE * fp;
	char line[STRING_SIZE];
	char word[STRING_SIZE];
	int last_index = -1, server_counter = 0, learner_id;

	fp = fopen(config_file, "r");
	while (!feof(fp)) {
		if (fgets(line, STRING_SIZE, fp) != 0) {
			last_index = get_substr(0, strlen(line) - 1, line, word);

			if (strcmp(word, match) == 0) {

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				if (flag == 'a')
					config->server_infos[server_counter].server_id = atoi(word);
				else if (flag == 't')
					learner_id = atoi(word);
				else if (flag == 'l')
					config->learner_infos[server_counter].learner_id = atoi(word);

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				if (flag == 'a')
					memcpy(config->server_infos[server_counter].ip, word, strlen(word));
				else if (flag == 't')
					config->learner_infos[learner_id].acceptor_id = atoi(word);
				if (flag == 'l')
					memcpy(config->learner_infos[server_counter].ip, word, strlen(word));

				if (flag != 't') {
					last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
					if (flag == 'a')
						config->server_infos[server_counter].port = atoi(word);
					if (flag == 'l')
						config->learner_infos[server_counter].acceptor_port = atoi(word);
				}
				server_counter++;
			}
		}
	}
	if (flag == 'a')
		config->total_num_acceptors = server_counter;
	else if (flag == 'l')
		config->total_num_learners = server_counter;

	fclose(fp);
}
//-------------------------------------------------------------
void get_multicast_address(const char* config_file, config_info * config, const char * match) {

	FILE * fp;
	char line[STRING_SIZE], word[STRING_SIZE];
	int last_index = -1;

	fp = fopen(config_file, "r");
	while (!feof(fp)) {
		if (fgets(line, STRING_SIZE, fp) != 0) {
			last_index = get_substr(0, strlen(line) - 1, line, word);
			if (strcmp(word, match) == 0) {
				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				strcpy(config->multicast_ip, word);

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				config->multicast_port = atoi(word);
			}
		}
	}
	fclose(fp);
}
//-------------------------------------------------------------  
void get_multicast_address_for_proposer(const char* config_file, config_info * config, const char * match) {

	FILE * fp;
	char line[STRING_SIZE], word[STRING_SIZE];
	int last_index = -1;

	fp = fopen(config_file, "r");
	while (!feof(fp)) {
		if (fgets(line, STRING_SIZE, fp) != 0) {
			last_index = get_substr(0, strlen(line) - 1, line, word);
			if (strcmp(word, match) == 0) {
				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				config->proposer_to_multicaster_port = atoi(word);
			}
		}
	}
	fclose(fp);
}
//-------------------------------------------------------------
void form_ring(config_info *config) {

	if (config->self_id != config->total_num_acceptors - 1) {
		config->server_infos[config->self_id].self_sid = create_udp_server_socket(config->server_infos[config->self_id].ip, config->server_infos[config->self_id].port);
		config->server_infos[config->self_id].successor_sid = create_udp_client_socket(config->server_infos[config->self_id + 1].ip, config->server_infos[config->self_id + 1].port);
	} else {
		config->server_infos[config->self_id].self_sid = create_udp_server_socket(config->server_infos[config->self_id].ip, config->server_infos[config->self_id].port);
		config->server_infos[config->self_id].successor_sid = create_udp_client_socket(config->server_infos[0].ip, config->server_infos[0].port);
	}

}

void create_sockets(config_info *config) {

	if (config->self_id == 1) {
		//pick one of the learner's port'
		int port = config->learner_infos[0].acceptor_port;
		create_tcp_server_socket_for_star(config->server_infos[config->self_id].ip, port, config->num_learners_to_connect_to_one_acceptor);
	}

	if (config->self_id == 0) {
		config->server_infos[config->self_id].multicast_send_sid = create_ip_multicast_sender_socket(config->multicast_ip);
		config->server_infos[config->self_id].proposer_recv_sid = create_udp_server_socket(config->server_infos[config->self_id].ip, config_info_sample->proposer_to_multicaster_port);
	} else {
		config->server_infos[config->self_id].multicast_recv_sid = create_ip_multicast_receiver_socket(config->multicast_ip, config->server_infos[config->self_id].ip, config->multicast_port);
	}

}

int find_learner_given_ip(config_info *config, char ip[INET_ADDRSTRLEN]) {
	int i = 0;

	for (i = 0; i < config->total_num_learners; i++) {
		if (strcmp(ip, config->learner_infos[i].ip) == 0) {
			printf("%s.%s.\n", ip, config->learner_infos[i].ip);
			return i;
		}
	}

	return -1;
}

//int find_learner_index_given_id(config_info *config, int learner_id, int server_id) {
//	int i = 0;
//
//	for (i = 0; i < config->learner_tcp_sid_count; i++) {
//		if (learner_id == (int) config->server_infos[server_id].learner_tcp_acceptor[i].learner_id) {
//			return i;
//		}
//	}
//	return -1;
//}
//--------getters------------
struct sockaddr_in* GET_SOCKADDR() {
	return getAddr(config_info_sample->multicast_port, config_info_sample->multicast_ip);
}
